// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.photoeditor.demo.model.mlkit.facedetection;

import android.app.Activity;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.common.base.log.DLog;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.face.FirebaseVisionFace;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions;
import com.photoeditor.demo.model.mlkit.OnDetectFaceListener;
import com.photoeditor.demo.model.mlkit.VisionProcessorBase;
import com.photoeditor.demo.model.mlkit.common.FrameMetadata;
import com.photoeditor.demo.model.mlkit.common.GraphicOverlay;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Face Detector Demo.
 */
public class FaceDetectionProcessor extends VisionProcessorBase<List<FirebaseVisionFace>> {

    private static final String TAG = "FaceDetectionProcessor";

    private FirebaseVisionFaceDetector detector;

    private OnDetectFaceListener mOnDetectFaceListener;

    public FaceDetectionProcessor() {
        FirebaseVisionFaceDetectorOptions options =
                new FirebaseVisionFaceDetectorOptions.Builder()
                        .setClassificationMode(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
                        .build();
        try {
            detector = FirebaseVision.getInstance().getVisionFaceDetector(options);
        } catch (Exception e) {
        }
    }

    @Override
    public void stop() {
        try {
            if (detector != null) {
                detector.close();
            }
        } catch (IOException e) {
            DLog.e(TAG, "Exception thrown while trying to close Face Detector: " + e);
        }
    }

    @Override
    protected Task<List<FirebaseVisionFace>> detectInImage(FirebaseVisionImage image) {
        if (detector != null) {
            return detector.detectInImage(image);
        } else {
            return new Task<List<FirebaseVisionFace>>() {
                @Override
                public boolean isComplete() {
                    return false;
                }

                @Override
                public boolean isSuccessful() {
                    return false;
                }

                @Override
                public boolean isCanceled() {
                    return false;
                }

                @Nullable
                @Override
                public List<FirebaseVisionFace> getResult() {
                    return new ArrayList<>();
                }

                @Nullable
                @Override
                public <X extends Throwable> List<FirebaseVisionFace> getResult(@NonNull Class<X> aClass) throws X {
                    return new ArrayList<>();
                }

                @Nullable
                @Override
                public Exception getException() {
                    return null;
                }

                @NonNull
                @Override
                public Task<List<FirebaseVisionFace>> addOnSuccessListener(@NonNull OnSuccessListener<? super List<FirebaseVisionFace>> onSuccessListener) {
                    return null;
                }

                @NonNull
                @Override
                public Task<List<FirebaseVisionFace>> addOnSuccessListener(@NonNull Executor executor, @NonNull OnSuccessListener<? super List<FirebaseVisionFace>> onSuccessListener) {
                    return null;
                }

                @NonNull
                @Override
                public Task<List<FirebaseVisionFace>> addOnSuccessListener(@NonNull Activity activity, @NonNull OnSuccessListener<? super List<FirebaseVisionFace>> onSuccessListener) {
                    return null;
                }

                @NonNull
                @Override
                public Task<List<FirebaseVisionFace>> addOnFailureListener(@NonNull OnFailureListener onFailureListener) {
                    return null;
                }

                @NonNull
                @Override
                public Task<List<FirebaseVisionFace>> addOnFailureListener(@NonNull Executor executor, @NonNull OnFailureListener onFailureListener) {
                    return null;
                }

                @NonNull
                @Override
                public Task<List<FirebaseVisionFace>> addOnFailureListener(@NonNull Activity activity, @NonNull OnFailureListener onFailureListener) {
                    return null;
                }
            };
        }
    }

    @Override
    protected void onSuccess(
            @Nullable Bitmap originalCameraImage,
            @NonNull List<FirebaseVisionFace> faces,
            @NonNull FrameMetadata frameMetadata,
            @NonNull GraphicOverlay graphicOverlay) {
        if (mOnDetectFaceListener != null) {
            mOnDetectFaceListener.onDetectFaceSuccess(faces);
        }

        /*graphicOverlay.clear();
        if (originalCameraImage != null) {
            CameraImageGraphic imageGraphic = new CameraImageGraphic(graphicOverlay, originalCameraImage);
            graphicOverlay.add(imageGraphic);
        }
        for (int i = 0; i < faces.size(); ++i) {
            FirebaseVisionFace face = faces.get(i);

            int cameraFacing =
                    frameMetadata != null ? frameMetadata.getCameraFacing() :
                            Camera.CameraInfo.CAMERA_FACING_BACK;
            FaceGraphic faceGraphic = new FaceGraphic(graphicOverlay, face, cameraFacing);
            graphicOverlay.add(faceGraphic);
        }
        graphicOverlay.postInvalidate();*/
    }

    @Override
    protected void onFailure(@NonNull Exception e) {
        if (mOnDetectFaceListener != null) {
            mOnDetectFaceListener.onDetectFaceFailure(e);
        }
    }

    public void setOnDetectFaceListener(OnDetectFaceListener onDetectFaceListener) {
        mOnDetectFaceListener = onDetectFaceListener;
    }
}
